package com.xlf.service.base.service.importProblem.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xlf.common.core.constant.Constants;
import com.xlf.common.core.util.StringUtils;
import com.xlf.pojo.base.ProblemCase;
import com.xlf.service.base.service.importProblem.AbstractImportService;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author xlf 2734029211@qq.com
 * @Date 2023/11/29 16:15
 * @Description: TODO 测试用例压缩包处理
 * @Version 1.0
 */
public class ProblemCaseImportService extends AbstractImportService {

    /**
     * 上传一个测试用例压缩包，解析后生成测试用例列表
     * @param file 测试用例压缩包
     * @return 测试用例列表
     */
    public List<ProblemCase> uploadTestcaseZip(MultipartFile file) {

        String fileDir = initWorkFileDir(file);
        return getProblemCases(fileDir);
    }

    /**
     * 解析文件夹里面的文件并生成获取测试用例
     * @param fileDir 测试用例文件夹路径
     * @return 测试用例列表
     */
    public ArrayList<ProblemCase> getProblemCases(String fileDir) {

        File testCaseFileList = new File(fileDir);
        return getProblemCases(testCaseFileList);

    }

    /**
     * 解析文件夹里面的文件并生成获取测试用例
     * @param testCaseFileList 测试用例文件夹
     * @return 测试用例列表
     */
    public ArrayList<ProblemCase> getProblemCases(File testCaseFileList) {

        File[] files = testCaseFileList.listFiles();
        if (files == null || files.length == 0) {
            return new ArrayList<>();
        }

        Map<String, File> inputData = new TreeMap<>();

        Map<String, File> outputData = new HashMap<>();

        //测试用例格外消息文件夹

        File testCaseInfoFile = null;
        // 遍历读取与检查是否in和out文件一一对应，否则报错
        for (File tmp : files) {
            String tmpPreName = null;
            if (tmp.getName().endsWith(".in")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".in"));
                inputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".out")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".out"));
                outputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".ans")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".ans"));
                outputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".txt")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".txt"));
                if (tmpPreName.contains("input")) {
                    inputData.put(tmpPreName.replaceAll("input", "*"), tmp);
                } else if (tmpPreName.contains("output")) {
                    outputData.put(tmpPreName.replaceAll("output", "*"), tmp);
                }
            } else if(tmp.getName().endsWith(".json")){
                testCaseInfoFile = tmp;
            }
        }

        ArrayList<ProblemCase> problemCases = new ArrayList<>();

        if(StringUtils.isEmpty(inputData))
            return problemCases;


        /**
         * [
         * {
         * name : "文件名",
         * score : 分数,
         * seq : 顺序
         * },
         * ]
         */
        JSONArray testCasesInfo = new JSONArray();
        if(testCaseInfoFile.exists())
            testCasesInfo = JSONUtil.readJSONArray(testCaseInfoFile, StandardCharsets.UTF_8);

        HashMap<String, JSONObject> testCaseInfoMap = new HashMap<>();

        for (Object item : testCasesInfo) {
            JSONObject jsonObject = (JSONObject)item;
            String name = jsonObject.getStr("name");
            if(StringUtils.isNotEmpty(name))
                testCaseInfoMap.put(name,jsonObject);
        }

        AtomicInteger seq = new AtomicInteger(1);
        inputData.forEach((k,v) ->{

            String input = FileUtil.readUtf8String(v);
            String output = null;
            if(outputData.containsKey(k))
                output = FileUtil.readUtf8String(outputData.get(k));

            ProblemCase problemCase = new ProblemCase();
            problemCase.setInput(input);
            problemCase.setOutput(output);
            JSONObject testCaseInfo = testCaseInfoMap.getOrDefault(k,new JSONObject());
            problemCase.setSeq(Optional.ofNullable(testCaseInfo.getInt("seq")).orElse(seq.getAndIncrement()));
            problemCase.setScore(testCaseInfo.getInt("score",10));
            problemCase.setStatus(Constants.NORMAL);
            problemCases.add(problemCase);
        });

        return problemCases;
    }



    /**
     * 解析文件夹里面的文件并生成获取测试用例
     * @param testCaseFileList 测试用例文件夹
     * @return 测试用例Map, key为输入文件名
     */
    public Map<String,ProblemCase> getProblemCasesMap(File testCaseFileList) {

        File[] files = testCaseFileList.listFiles();
        if (files == null || files.length == 0) {
            return new HashMap<>();
        }

        Map<String, File> inputData = new TreeMap<>();

        Map<String, File> outputData = new HashMap<>();

        // 遍历读取与检查是否in和out文件一一对应，否则报错
        for (File tmp : files) {
            String tmpPreName = null;
            if (tmp.getName().endsWith(".in")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".in"));
                inputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".out")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".out"));
                outputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".ans")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".ans"));
                outputData.put(tmpPreName, tmp);
            } else if (tmp.getName().endsWith(".txt")) {
                tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf(".txt"));
                if (tmpPreName.contains("input")) {
                    inputData.put(tmpPreName.replaceAll("input", "*"), tmp);
                } else if (tmpPreName.contains("output")) {
                    outputData.put(tmpPreName.replaceAll("output", "*"), tmp);
                }
            }
        }

        HashMap<String, ProblemCase> stringProblemCaseHashMap = new HashMap<>();

        if(StringUtils.isEmpty(inputData))
            return stringProblemCaseHashMap;

        AtomicInteger seq = new AtomicInteger(1);
        inputData.forEach((k,v) ->{
            String input = FileUtil.readUtf8String(v);
            String output = null;
            if(outputData.containsKey(k)){
                output = FileUtil.readUtf8String(outputData.get(k));
            }
            ProblemCase problemCase = new ProblemCase();
            problemCase.setInput(input);
            problemCase.setOutput(output);
            problemCase.setSeq(seq.getAndIncrement());
            problemCase.setScore(100);
            problemCase.setStatus(Constants.NORMAL);
            stringProblemCaseHashMap.put(k,problemCase);
        });

        return stringProblemCaseHashMap;
    }
}
